﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using HeartLess.GameObjects;
using Microsoft.Xna.Framework;
using HeartLess.Managers;

namespace HeartLess.LevelData
{
    public static class LevelLoader
    {

        private const String LEVEL_FILE_LOCATION_TEMPLATE = "Content/Levels/Level{0}.xml";

        private const String ATTR_THEME = "Theme";
        private const String ATTR_LOC_X = "X-Loc";
        private const String ATTR_LOC_Y = "Y-Loc";
        private const String ATTR_NUM_COL = "NumCol";
        private const String ATTR_NUM_ROW = "NumRow";
        private const String ATTR_DEMON_SKIN = "Skin"; 
        private const String ATTR_HEALTH = "Health";
        private const String ATTR_HEART_RATE = "HeartRate";
        private const String ATTR_TIME = "Time";
        private const String ATTR_FLOATING = "Floating";

        private const String TYPE_LEVEL_DATA = "LevelData";
        private const String TYPE_PLAYER = "Player";
        private const String TYPE_BLOCK_NORMAL = "NormalBlock";
        private const String TYPE_BLOCK_END = "EndBlock";
        private const String TYPE_DEMON = "Demon";
        private const String TYPE_HEALTH = "Health";
        private const String TYPE_HEARTRATE = "HeartRate";
        
        public static Level LoadLevel(int levelNumber)
        {
            String levelFile = String.Format(LEVEL_FILE_LOCATION_TEMPLATE, levelNumber);
            XmlTextReader levelXmlReader = new XmlTextReader(levelFile);

            Level level = null;
            
            while (levelXmlReader.Read())
            {
                if (levelXmlReader.NodeType == XmlNodeType.Element && levelXmlReader.HasAttributes)
                {
                    int xLoc = Convert.ToInt32(levelXmlReader.GetAttribute(ATTR_LOC_X));
                    int yLoc = Convert.ToInt32(levelXmlReader.GetAttribute(ATTR_LOC_Y));
                    Point location = new Point(xLoc, yLoc);

                    switch (levelXmlReader.Name)
                    {
                        case TYPE_LEVEL_DATA:
                            string theme = levelXmlReader.GetAttribute(ATTR_THEME);
                            level = new Level(theme);
                            break;
                        
                        case TYPE_BLOCK_NORMAL:
                            int cols = Convert.ToInt32(levelXmlReader.GetAttribute(ATTR_NUM_COL));
                            int rows = Convert.ToInt32(levelXmlReader.GetAttribute(ATTR_NUM_ROW));
                            String floating = levelXmlReader.GetAttribute(ATTR_FLOATING);
                            bool f = floating != null && Convert.ToInt32(floating) != 0;

                            for (int col = xLoc; col < xLoc + cols; col++)
                            {
                                for (int row = yLoc; row < yLoc + rows; row++)
                                {
                                    Point loc = new Point(col, row);
                                    Block block = new Block(loc, f);
                                    level.AddBlock(block);
                                }
                            }

                            break;

                        case TYPE_BLOCK_END:
                            String endFloating = levelXmlReader.GetAttribute(ATTR_FLOATING);
                            bool fEnd = endFloating != null && Convert.ToInt32(endFloating) != 0;
                            EndBlock endBlock = new EndBlock(location, fEnd);
                            level.AddBlock(endBlock);
                            break;

                        case TYPE_PLAYER:
                            Single health = Convert.ToSingle(levelXmlReader.GetAttribute(ATTR_HEALTH));
                            Single heartRate = Convert.ToSingle(levelXmlReader.GetAttribute(ATTR_HEART_RATE));
                            Player player = new Player(location, health, heartRate);
                            level.Player = player;
                            break;

                        case TYPE_HEALTH:
                            Single healthDelta = Convert.ToSingle(levelXmlReader.GetAttribute(ATTR_HEALTH));
                            HealthModifier healthModifier = new HealthModifier(level.Player, location, healthDelta);
                            level.AddModifier(healthModifier);
                            break;

                        case TYPE_HEARTRATE:
                            Single time = Convert.ToSingle(levelXmlReader.GetAttribute(ATTR_TIME));
                            Single heartRateDelta = Convert.ToSingle(levelXmlReader.GetAttribute(ATTR_HEART_RATE));
                            HeartRateModifier hrModifier = new HeartRateModifier(level.Player, location, heartRateDelta, time);
                            level.AddModifier(hrModifier);
                            break;

                        case TYPE_DEMON:

                            String skin = levelXmlReader.GetAttribute(ATTR_DEMON_SKIN);
                            Demon demon = new Demon(location, level.Player, skin);

                            level.AddEnemy(demon);
                            break;

                        default:
                            throw new Exception("Unknown XML Node Type: " + levelXmlReader.Name);
                    }
                }
            }

            return level;
        }

    }
}
